/**
  ******************************************************************************
  * @file	enc28j60.h
  * @author  A mix of different versions from Internet. Edited by Nightmare
  * @version V1.0.0
  * @date	2015.1.29
  * @brief   
  ******************************************************************************
  *
  ******************************************************************************
  */



#ifndef __ENC28J60_H
#define __ENC28J60_H

#include "stm32f0xx.h"

// ENC28J60 Control Registers
// Control register definitions are a combination of address,
// bank number, and Ethernet/MAC/PHY indicator bits.
// - Register address		 (bits 0-4)
// - Bank number			  (bits 5-6)
// - MAC/PHY indicator		(bit 7)

#define ADDR_MASK		0x1F
#define BANK_MASK		0x60
#define SPRD_MASK		0x80
// All-bank registers
#define EIE			  0x1B
#define EIR			  0x1C
#define ESTAT			0x1D
#define ECON2			0x1E
#define ECON1			0x1F
// Bank 0 registers
#define ERDPTL		   (0x00|0x00)
#define ERDPTH		   (0x01|0x00)
#define EWRPTL		   (0x02|0x00)
#define EWRPTH		   (0x03|0x00)
#define ETXSTL		   (0x04|0x00)
#define ETXSTH		   (0x05|0x00)
#define ETXNDL		   (0x06|0x00)
#define ETXNDH		   (0x07|0x00)
#define ERXSTL		   (0x08|0x00)
#define ERXSTH		   (0x09|0x00)
#define ERXNDL		   (0x0A|0x00)
#define ERXNDH		   (0x0B|0x00)


#define ERXRDPTL		 (0x0C|0x00)
#define ERXRDPTH		 (0x0D|0x00)
#define ERXWRPTL		 (0x0E|0x00)
#define ERXWRPTH		 (0x0F|0x00)
#define EDMASTL		  (0x10|0x00)
#define EDMASTH		  (0x11|0x00)
#define EDMANDL		  (0x12|0x00)
#define EDMANDH		  (0x13|0x00)
#define EDMADSTL		 (0x14|0x00)
#define EDMADSTH		 (0x15|0x00)
#define EDMACSL		  (0x16|0x00)
#define EDMACSH		  (0x17|0x00)
// Bank 1 registers
#define EHT0			 (0x00|0x20)
#define EHT1			 (0x01|0x20)
#define EHT2			 (0x02|0x20)
#define EHT3			 (0x03|0x20)
#define EHT4			 (0x04|0x20)
#define EHT5			 (0x05|0x20)
#define EHT6			 (0x06|0x20)
#define EHT7			 (0x07|0x20)
#define EPMM0			(0x08|0x20)
#define EPMM1			(0x09|0x20)
#define EPMM2			(0x0A|0x20)
#define EPMM3			(0x0B|0x20)
#define EPMM4			(0x0C|0x20)
#define EPMM5			(0x0D|0x20)
#define EPMM6			(0x0E|0x20)
#define EPMM7			(0x0F|0x20)
#define EPMCSL		   (0x10|0x20)
#define EPMCSH		   (0x11|0x20)
#define EPMOL			(0x14|0x20)
#define EPMOH			(0x15|0x20)
#define EWOLIE		   (0x16|0x20)
#define EWOLIR		   (0x17|0x20)
#define ERXFCON		  (0x18|0x20)
#define EPKTCNT		  (0x19|0x20)
// Bank 2 registers
#define MACON1		   (0x00|0x40|0x80)
#define MACON2		   (0x01|0x40|0x80)
#define MACON3		   (0x02|0x40|0x80)
#define MACON4		   (0x03|0x40|0x80)
#define MABBIPG		  (0x04|0x40|0x80)
#define MAIPGL		   (0x06|0x40|0x80)
#define MAIPGH		   (0x07|0x40|0x80)
#define MACLCON1		 (0x08|0x40|0x80)
#define MACLCON2		 (0x09|0x40|0x80)
#define MAMXFLL		  (0x0A|0x40|0x80)
#define MAMXFLH		  (0x0B|0x40|0x80)
#define MAPHSUP		  (0x0D|0x40|0x80)
#define MICON			(0x11|0x40|0x80)
#define MICMD			(0x12|0x40|0x80)
#define MIREGADR		 (0x14|0x40|0x80)
#define MIWRL			(0x16|0x40|0x80)
#define MIWRH			(0x17|0x40|0x80)
#define MIRDL			(0x18|0x40|0x80)
#define MIRDH			(0x19|0x40|0x80)
// Bank 3 registers
#define MAADR1		   (0x00|0x60|0x80)
#define MAADR0		   (0x01|0x60|0x80)
#define MAADR3		   (0x02|0x60|0x80)
#define MAADR2		   (0x03|0x60|0x80)
#define MAADR5		   (0x04|0x60|0x80)
#define MAADR4		   (0x05|0x60|0x80)
#define EBSTSD		   (0x06|0x60)
#define EBSTCON		  (0x07|0x60)
#define EBSTCSL		  (0x08|0x60)
#define EBSTCSH		  (0x09|0x60)
#define MISTAT		   (0x0A|0x60|0x80)
#define EREVID		   (0x12|0x60)
#define ECOCON		   (0x15|0x60)
#define EFLOCON		  (0x17|0x60)
#define EPAUSL		   (0x18|0x60)
#define EPAUSH		   (0x19|0x60)
// PHY registers
#define PHCON1		   0x00
#define PHSTAT1		  0x01
#define PHHID1		   0x02
#define PHHID2		   0x03
#define PHCON2		   0x10
#define PHSTAT2		  0x11
#define PHIE			 0x12
#define PHIR			 0x13
#define PHLCON		   0x14

// ENC28J60 ERXFCON Register Bit Definitions
#define ERXFCON_UCEN	 0x80
#define ERXFCON_ANDOR	0x40
#define ERXFCON_CRCEN	0x20
#define ERXFCON_PMEN	 0x10
#define ERXFCON_MPEN	 0x08
#define ERXFCON_HTEN	 0x04
#define ERXFCON_MCEN	 0x02
#define ERXFCON_BCEN	 0x01
// ENC28J60 EIE Register Bit Definitions
#define EIE_INTIE		0x80
#define EIE_PKTIE		0x40
#define EIE_DMAIE		0x20
#define EIE_LINKIE	   0x10
#define EIE_TXIE		 0x08
#define EIE_WOLIE		0x04
#define EIE_TXERIE	   0x02
#define EIE_RXERIE	   0x01
// ENC28J60 EIR Register Bit Definitions
#define EIR_PKTIF		0x40
#define EIR_DMAIF		0x20
#define EIR_LINKIF	   0x10
#define EIR_TXIF		 0x08
#define EIR_WOLIF		0x04
#define EIR_TXERIF	   0x02
#define EIR_RXERIF	   0x01
// ENC28J60 ESTAT Register Bit Definitions
#define ESTAT_INT		0x80
#define ESTAT_LATECOL	0x10
#define ESTAT_RXBUSY	 0x04
#define ESTAT_TXABRT	 0x02
#define ESTAT_CLKRDY	 0x01
// ENC28J60 ECON2 Register Bit Definitions
#define ECON2_AUTOINC	0x80
#define ECON2_PKTDEC	 0x40
#define ECON2_PWRSV	  0x20
#define ECON2_VRPS	   0x08
// ENC28J60 ECON1 Register Bit Definitions
#define ECON1_TXRST	  0x80
#define ECON1_RXRST	  0x40
#define ECON1_DMAST	  0x20
#define ECON1_CSUMEN	 0x10
#define ECON1_TXRTS	  0x08
#define ECON1_RXEN	   0x04
#define ECON1_BSEL1	  0x02
#define ECON1_BSEL0	  0x01
// ENC28J60 MACON1 Register Bit Definitions
#define MACON1_LOOPBK	0x10
#define MACON1_TXPAUS	0x08
#define MACON1_RXPAUS	0x04
#define MACON1_PASSALL   0x02
#define MACON1_MARXEN	0x01
// ENC28J60 MACON2 Register Bit Definitions
#define MACON2_MARST	 0x80
#define MACON2_RNDRST	0x40
#define MACON2_MARXRST   0x08
#define MACON2_RFUNRST   0x04
#define MACON2_MATXRST   0x02
#define MACON2_TFUNRST   0x01
// ENC28J60 MACON3 Register Bit Definitions
#define MACON3_PADCFG2   0x80
#define MACON3_PADCFG1   0x40
#define MACON3_PADCFG0   0x20
#define MACON3_TXCRCEN   0x10
#define MACON3_PHDRLEN   0x08
#define MACON3_HFRMLEN   0x04
#define MACON3_FRMLNEN   0x02
#define MACON3_FULDPX	0x01
// ENC28J60 MICMD Register Bit Definitions
#define MICMD_MIISCAN	0x02
#define MICMD_MIIRD	  0x01
// ENC28J60 MISTAT Register Bit Definitions
#define MISTAT_NVALID	0x04
#define MISTAT_SCAN	  0x02
#define MISTAT_BUSY	  0x01
// ENC28J60 PHY PHCON1 Register Bit Definitions
#define PHCON1_PRST	  0x8000
#define PHCON1_PLOOPBK   0x4000
#define PHCON1_PPWRSV	0x0800
#define PHCON1_PDPXMD	0x0100
// ENC28J60 PHY PHSTAT1 Register Bit Definitions
#define PHSTAT1_PFDPX	0x1000
#define PHSTAT1_PHDPX	0x0800
#define PHSTAT1_LLSTAT   0x0004
#define PHSTAT1_JBSTAT   0x0002
// ENC28J60 PHY PHCON2 Register Bit Definitions
#define PHCON2_FRCLINK   0x4000
#define PHCON2_TXDIS	 0x2000
#define PHCON2_JABBER	0x0400
#define PHCON2_HDLDIS	0x0100

// ENC28J60 Packet Control Byte Bit Definitions
#define PKTCTRL_PHUGEEN  0x08
#define PKTCTRL_PPADEN   0x04
#define PKTCTRL_PCRCEN   0x02
#define PKTCTRL_POVERRIDE 0x01

// SPI operation codes
#define ENC28J60_READ_CTRL_REG	   0x00
#define ENC28J60_READ_BUF_MEM		0x3A
#define ENC28J60_WRITE_CTRL_REG	  0x40
#define ENC28J60_WRITE_BUF_MEM	   0x7A
#define ENC28J60_BIT_FIELD_SET	   0x80
#define ENC28J60_BIT_FIELD_CLR	   0xA0
#define ENC28J60_SOFT_RESET		  0xFF

// Work around E5
// The RXSTART_INIT should be zero. See Rev. B4 Silicon Errata
// buffer boundaries applied to internal 8K ram
// the entire available packet buffer space is allocated
//
// start with recbuf at 0/
#define RXSTART_INIT	 0x0
// receive buffer end
#define RXSTOP_INIT	  (0x1FFF-0x0800-1)
// start TX buffer at 0x1FFF-0x0600, pace for one full ethernet frame (~1500 bytes)
#define TXSTART_INIT	 (0x1FFF-0x0800)
// stp TX buffer at end of mem
#define TXSTOP_INIT	  0x1FFF

//
//#define RXSTART_INIT	  0			   //errata 5
// receive buffer end
//#define RXSTOP_INIT	  6143
// start TX buffer at 0x1FFF-0x0600, pace for one full ethernet frame (~1500 bytes)
//#define TXSTART_INIT	 6144
// stp TX buffer at end of mem
//#define TXSTOP_INIT	  8191
////



// max frame length which the conroller will accept:
#define		MAX_FRAMELEN		1518		// (note: maximum ethernet frame length would be 1518)
//#define MAX_FRAMELEN	 600

enum ENC28J60_LINK_STATE
{
	ENC_LINK_DOWN = 0,
	ENC_LINK_UP = 1
};


typedef union _WORD_VAL
{
	uint16_t Val;
	uint8_t v[2];
	struct
	{
		uint8_t LB;
		uint8_t HB;
	} byte;
	struct
	{
		uint8_t b0:1;
		uint8_t b1:1;
		uint8_t b2:1;
		uint8_t b3:1;
		uint8_t b4:1;
		uint8_t b5:1;
		uint8_t b6:1;
		uint8_t b7:1;
		uint8_t b8:1;
		uint8_t b9:1;
		uint8_t b10:1;
		uint8_t b11:1;
		uint8_t b12:1;
		uint8_t b13:1;
		uint8_t b14:1;
		uint8_t b15:1;
	} bits;
} WORD_VAL, WORD_BITS;

typedef union {
	uint8_t v[7];
	struct {
		uint16_t ByteCount;
		uint8_t	CollisionCount:4;
		uint8_t	CRCError:1;
		uint8_t	LengthCheckError:1;
		uint8_t	LengthOutOfRange:1;
		uint8_t	Done:1;
		uint8_t	Multicast:1;
		uint8_t	Broadcast:1;
		uint8_t	PacketDefer:1;
		uint8_t	ExcessiveDefer:1;
		uint8_t	MaximumCollisions:1;
		uint8_t	LateCollision:1;
		uint8_t	Giant:1;
		uint8_t	Underrun:1;
		uint16_t BytesTransmittedOnWire;
		uint8_t	ControlFrame:1;
		uint8_t	PAUSEControlFrame:1;
		uint8_t	BackpressureApplied:1;
		uint8_t	VLANTaggedFrame:1;
		uint8_t	Zeros:4;
	} bits;
} TXSTATUS;


void 	ENC28J60_Init(uint8_t* macaddr);

uint8_t ENC28J60_OpRead(uint8_t op, uint8_t address);
void 	ENC28J60_OpWrite(uint8_t op, uint8_t address, uint8_t data);
void 	ENC28J60_BufferRead(uint32_t len, uint8_t* data);
void 	ENC28J60_BufferWrite(uint32_t len, uint8_t* data);
void 	ENC28J60_SetBank(uint8_t address);
uint8_t ENC28J60_RegRead(uint8_t address);
void 	ENC28J60_RegWrite(uint8_t address, uint8_t data);
void 	ENC28J60_PhyWrite(uint8_t address, uint32_t data);
uint32_t ENC28J60_PhyRead(uint8_t address); 

void ENC28J60_PacketSend(uint8_t* packet, uint32_t len);
uint32_t ENC28J60_PacketReceive(uint8_t* packet, uint32_t maxlen);

uint8_t ENC28J60_GetVersion(void);
uint8_t  ENC28J60_GetLinkStatus(void);
void 	ENC28J60_clkout(uint8_t clk);
#endif /* __ENC28J60_H */
